<template>
    <div>
        <el-drawer v-bind="$attrs" v-on="$listeners" @opened="onOpen" @close="onClose">
            <div style="height:100%">
                <el-row style="height:100%;overflow:auto">
                    <el-col :md="24" :lg="12" class="left-editor">
                        <div class="setting" title="资源引用" @click="showResource">
                            <el-badge :is-dot="!!resources.length" class="item">
                                <i class="el-icon-setting"/>
                            </el-badge>
                        </div>
                        <el-tabs v-model="activeTab" type="card" class="editor-tabs">
                            <el-tab-pane name="html">
                                <span slot="label">
                                  <i v-if="activeTab==='html'" class="el-icon-edit"/>
                                  <i v-else class="el-icon-document"/>
                                  template
                                </span>
                            </el-tab-pane>
                            <el-tab-pane name="js">
                                <span slot="label">
                                  <i v-if="activeTab==='js'" class="el-icon-edit"/>
                                  <i v-else class="el-icon-document"/>
                                  script
                                </span>
                            </el-tab-pane>
                            <el-tab-pane name="css">
                                <span slot="label">
                                  <i v-if="activeTab==='css'" class="el-icon-edit"/>
                                  <i v-else class="el-icon-document"/>
                                  css
                                </span>
                            </el-tab-pane>
                        </el-tabs>
                        <div v-show="activeTab==='html'" id="editorHtml" class="tab-editor"/>
                        <div v-show="activeTab==='js'" id="editorJs" class="tab-editor"/>
                        <div v-show="activeTab==='css'" id="editorCss" class="tab-editor"/>
                    </el-col>
                    <el-col :md="24" :lg="12" class="right-preview">
                        <div class="action-bar" :style="{'text-align': 'left'}">
              <span class="bar-btn" @click="runCode">
                <i class="el-icon-refresh"/>
                刷新
              </span>
                            <span class="bar-btn" @click="exportFile">
                <i class="el-icon-download"/>
                导出vue文件
              </span>
                            <span ref="copyBtn" class="bar-btn copy-btn">
                <i class="el-icon-document-copy"/>
                复制代码
              </span>
                            <span class="bar-btn delete-btn" @click="$emit('update:visible', false)">
                <i class="el-icon-circle-close"/>
                关闭
              </span>
                        </div>
                        <iframe
                            v-show="isIframeLoaded"
                            ref="previewPage"
                            class="result-wrapper"
                            frameborder="0"
                            src="preview.html"
                            @load="iframeLoad"
                        />
                        <div v-show="!isIframeLoaded" v-loading="true" class="result-wrapper"/>
                    </el-col>
                </el-row>
            </div>
        </el-drawer>

    </div>
</template>
<script>
    import {parse} from '@babel/parser'
    import _ from 'lodash';

    const editorObj = {
        html: null,
        js: null,
        css: null
    }
    const mode = {
        html: 'html',
        js: 'javascript',
        css: 'css'
    }
    let beautifier
    let monaco

    export default {
        components: {},
        props: ['formData', 'generateConf'],
        data() {
            return {
                activeTab: 'html',
                htmlCode: '',
                jsCode: '',
                cssCode: '',
                codeFrame: '',
                isIframeLoaded: false,
                isInitcode: false, // 保证open后两个异步只执行一次runcode
                isRefreshCode: false, // 每次打开都需要重新刷新代码
                resourceVisible: false,
                scripts: [],
                links: [],
                monaco: null
            }
        },
        computed: {
            resources() {
                return this.scripts.concat(this.links)
            }
        },
        watch: {},
        created() {
        },
        mounted() {
            window.addEventListener('keydown', this.preventDefaultSave)
            // const clipboard = new ClipboardJS('.copy-btn', {
            //   text: trigger => {
            //     const codeStr = this.generateCode()
            //     this.$notify({
            //       title: '成功',
            //       message: '代码已复制到剪切板，可粘贴。',
            //       type: 'success'
            //     })
            //     return codeStr
            //   }
            // })
            // clipboard.on('error', e => {
            //   this.$message.error('代码复制失败')
            // })
        },
        beforeDestroy() {
            window.removeEventListener('keydown', this.preventDefaultSave)
        },
        methods: {
            preventDefaultSave(e) {
                if (e.key === 's' && (e.metaKey || e.ctrlKey)) {
                    e.preventDefault()
                }
            },
            onOpen() {
                // const {type} = this.generateConf
                // this.htmlCode = makeUpHtml(this.formData, type)
                // this.jsCode = makeUpJs(this.formData, type)
                // this.cssCode = makeUpCss(this.formData)

                // loadBeautifier(btf => {
                //     beautifier = btf
                //     this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html)
                //     this.jsCode = beautifier.js(this.jsCode, beautifierConf.js)
                //     this.cssCode = beautifier.css(this.cssCode, beautifierConf.html)
                //
                //     loadMonaco(val => {
                //         monaco = val
                //         this.setEditorValue('editorHtml', 'html', this.htmlCode)
                //         this.setEditorValue('editorJs', 'js', this.jsCode)
                //         this.setEditorValue('editorCss', 'css', this.cssCode)
                //         if (!this.isInitcode) {
                //             this.isRefreshCode = true
                //             this.isIframeLoaded && (this.isInitcode = true) && this.runCode()
                //         }
                //     })
                // })
            },
            onClose() {
                this.isInitcode = false
                this.isRefreshCode = false
            },
            iframeLoad() {
                if (!this.isInitcode) {
                    this.isIframeLoaded = true
                    this.isRefreshCode && (this.isInitcode = true) && this.runCode()
                }
            },
            setEditorValue(id, type, codeStr) {
                // if (editorObj[type]) {
                //     editorObj[type].setValue(codeStr)
                // } else {
                //     editorObj[type] = monaco.rich-editor.create(document.getElementById(id), {
                //         value: codeStr,
                //         theme: 'vs-dark',
                //         language: mode[type],
                //         automaticLayout: true
                //     })
                // }
                // // ctrl + s 刷新
                // editorObj[type].onKeyDown(e => {
                //     if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
                //         this.runCode()
                //     }
                // })
            },
            runCode() {
                const jsCodeStr = editorObj.js.getValue()
                try {
                    const ast = parse(jsCodeStr, {sourceType: 'module'})
                    const astBody = ast.program.body
                    if (astBody.length > 1) {
                        this.$confirm(
                            'js格式不能识别，仅支持修改export default的对象内容',
                            '提示',
                            {
                                type: 'warning'
                            }
                        )
                        return
                    }
                    if (astBody[0].type === 'ExportDefaultDeclaration') {
                        const postData = {
                            type: 'refreshFrame',
                            data: {
                                generateConf: this.generateConf,
                                html: editorObj.html.getValue(),
                                js: jsCodeStr.replace(exportDefault, ''),
                                css: editorObj.css.getValue(),
                                scripts: this.scripts,
                                links: this.links
                            }
                        }
                        // todo postMessage 不安全
                        // this.$refs.previewPage.contentWindow.postMessage(
                        //     postData,
                        //     location.origin
                        // )
                    } else {
                        this.$message.error('请使用export default')
                    }
                } catch (err) {
                    this.$message.error(`js错误：${err}`)
                    console.error(err)
                }
            },
            generateCode() {
                // const html = vueTemplate(editorObj.html.getValue())
                // const script = vueScript(editorObj.js.getValue())
                // const css = cssStyle(editorObj.css.getValue())
                // return beautifier.html(html + script + css, beautifierConf.html)
            },
            exportFile() {
                // this.$prompt('文件名:', '导出文件', {
                //     inputValue: `${+new Date()}.vue`,
                //     closeOnClickModal: false,
                //     inputPlaceholder: '请输入文件名'
                // }).then(({value}) => {
                //     if (!value) value = `${+new Date()}.vue`
                //     const codeStr = this.generateCode()
                //     const blob = new Blob([codeStr], {type: 'text/plain;charset=utf-8'})
                //     // saveAs(blob, value)
                // })
            },
            showResource() {
                this.resourceVisible = true
            },
            setResource(arr) {
                const scripts = [];
                const
                    links = []
                if (_.isArray(arr)) {
                    arr.forEach(item => {
                        if (item.endsWith('.css')) {
                            links.push(item)
                        } else {
                            scripts.push(item)
                        }
                    })
                    this.scripts = scripts
                    this.links = links
                } else {
                    this.scripts = []
                    this.links = []
                }
            }
        }
    }
</script>

<style lang="scss" scoped>
    @mixin action-bar {
        .action-bar {
            height: 33px;
            background: #f2fafb;
            padding: 0 15px;
            box-sizing: border-box;

            .bar-btn {
                display: inline-block;
                padding: 0 6px;
                line-height: 32px;
                color: #8285f5;
                cursor: pointer;
                font-size: 14px;
                user-select: none;

                & i {
                    font-size: 20px;
                }

                &:hover {
                    color: #4348d4;
                }
            }

            .bar-btn + .bar-btn {
                margin-left: 8px;
            }

            .delete-btn {
                color: #f56c6c;

                &:hover {
                    color: #ea0b30;
                }
            }
        }
    }

    .tab-editor {
        position: absolute;
        top: 33px;
        bottom: 0;
        left: 0;
        right: 0;
        font-size: 14px;
    }

    .left-editor {
        position: relative;
        height: 100%;
        background: #1e1e1e;
        overflow: hidden;
    }

    .setting {
        position: absolute;
        right: 15px;
        top: 3px;
        color: #a9f122;
        font-size: 18px;
        cursor: pointer;
        z-index: 1;
    }

    .right-preview {
        height: 100%;

        .result-wrapper {
            height: calc(100vh - 33px);
            width: 100%;
            overflow: auto;
            padding: 12px;
            box-sizing: border-box;
        }
    }

    @include action-bar;
    ::v-deep .el-drawer__header {
        display: none;
    }
</style>
